package job_types

import (
	"context"
	"fmt"
	"time"

	"gitlab.ctyuncdn.cn/tai/infra/cloud-controller/internal/job_manager"
	"gitlab.ctyuncdn.cn/tai/infra/cloud-controller/pkg/mysql"
)

// BatchJobTypeHandler handles batch processing jobs
type BatchJobTypeHandler struct {
	*BaseJobTypeHandler
}

// NewBatchJobTypeHandler creates a new batch job type handler
func NewBatchJobTypeHandler() *BatchJobTypeHandler {
	base := NewBaseJobTypeHandler(job_manager.JobTypeBatch, "Batch Processing job handler")

	// Add batch-specific parameters
	batchParams := []job_manager.Parameter{
		{
			Name:        "script_path",
			Type:        "string",
			Required:    true,
			Description: "Path to the batch processing script",
			Validation:  "script_path != ''",
		},
		{
			Name:        "input_path",
			Type:        "string",
			Required:    true,
			Description: "Path to the input data",
			Validation:  "input_path != ''",
		},
		{
			Name:        "output_path",
			Type:        "string",
			Required:    true,
			Description: "Path to save the output data",
			Validation:  "output_path != ''",
		},
		{
			Name:        "parallelism",
			Type:        "int",
			Required:    false,
			Default:     1,
			Description: "Number of parallel workers",
			Validation:  "parallelism > 0",
		},
		{
			Name:        "timeout",
			Type:        "int",
			Required:    false,
			Default:     3600,
			Description: "Job timeout in seconds",
			Validation:  "timeout > 0",
		},
		{
			Name:        "retry_count",
			Type:        "int",
			Required:    false,
			Default:     3,
			Description: "Number of retry attempts",
			Validation:  "retry_count >= 0",
		},
		{
			Name:        "memory_limit",
			Type:        "string",
			Required:    false,
			Default:     "2Gi",
			Description: "Memory limit for batch job",
			Validation:  "memory_limit != ''",
		},
	}

	// Combine base and batch-specific parameters
	allParams := append(base.supportedParameters, batchParams...)
	base.supportedParameters = allParams

	return &BatchJobTypeHandler{
		BaseJobTypeHandler: base,
	}
}

// ValidateJob validates a batch job
func (h *BatchJobTypeHandler) ValidateJob(job *mysql.Job) error {
	// Call base validation
	if err := h.BaseJobTypeHandler.ValidateJob(job); err != nil {
		return err
	}

	// Additional batch-specific validation
	if job.Parameters == "" {
		return fmt.Errorf("batch job requires parameters")
	}

	// TODO: Parse and validate batch-specific parameters
	// This would include checking for required script_path, input_path, output_path parameters

	return nil
}

// CreateResources creates resources for a batch job
func (h *BatchJobTypeHandler) CreateResources(ctx context.Context, job *mysql.Job) ([]*job_manager.Resource, error) {
	// Create batch-specific resources
	resources := []*job_manager.Resource{
		{
			Type:      "Job",
			Name:      fmt.Sprintf("batch-%s-job", job.JobID),
			Namespace: "batch",
			Spec: map[string]interface{}{
				"parallelism": "{{.Parallelism}}",
				"completions": "{{.Parallelism}}",
				"template": map[string]interface{}{
					"spec": map[string]interface{}{
						"restartPolicy": "OnFailure",
						"containers": []map[string]interface{}{
							{
								"name":  "batch-processor",
								"image": "busybox:latest",
								"command": []string{
									"sh",
									"-c",
									"{{.ScriptPath}} --input {{.InputPath}} --output {{.OutputPath}}",
								},
								"env": []map[string]interface{}{
									{
										"name":  "JOB_ID",
										"value": "{{.JobID}}",
									},
									{
										"name":  "PARALLELISM",
										"value": "{{.Parallelism}}",
									},
									{
										"name":  "TIMEOUT",
										"value": "{{.Timeout}}",
									},
								},
								"resources": map[string]interface{}{
									"requests": map[string]interface{}{
										"cpu":    "{{.CPU}}",
										"memory": "{{.Memory}}",
									},
									"limits": map[string]interface{}{
										"cpu":    "{{.CPULimit}}",
										"memory": "{{.MemoryLimit}}",
									},
								},
								"volumeMounts": []map[string]interface{}{
									{
										"name":      "batch-input",
										"mountPath": "/input",
									},
									{
										"name":      "batch-output",
										"mountPath": "/output",
									},
									{
										"name":      "batch-scripts",
										"mountPath": "/scripts",
									},
								},
							},
						},
						"volumes": []map[string]interface{}{
							{
								"name": "batch-input",
								"persistentVolumeClaim": map[string]interface{}{
									"claimName": fmt.Sprintf("batch-%s-input-pvc", job.JobID),
								},
							},
							{
								"name": "batch-output",
								"persistentVolumeClaim": map[string]interface{}{
									"claimName": fmt.Sprintf("batch-%s-output-pvc", job.JobID),
								},
							},
							{
								"name": "batch-scripts",
								"persistentVolumeClaim": map[string]interface{}{
									"claimName": fmt.Sprintf("batch-%s-scripts-pvc", job.JobID),
								},
							},
						},
					},
				},
			},
			Status: map[string]interface{}{
				"active":    0,
				"succeeded": 0,
				"failed":    0,
			},
			CreatedAt: time.Now(),
			UpdatedAt: time.Now(),
		},
		{
			Type:      "PersistentVolumeClaim",
			Name:      fmt.Sprintf("batch-%s-input-pvc", job.JobID),
			Namespace: "batch",
			Spec: map[string]interface{}{
				"accessModes": []string{"ReadWriteOnce"},
				"resources": map[string]interface{}{
					"requests": map[string]interface{}{
						"storage": "100Gi",
					},
				},
			},
			Status: map[string]interface{}{
				"phase": "Pending",
			},
			CreatedAt: time.Now(),
			UpdatedAt: time.Now(),
		},
		{
			Type:      "PersistentVolumeClaim",
			Name:      fmt.Sprintf("batch-%s-output-pvc", job.JobID),
			Namespace: "batch",
			Spec: map[string]interface{}{
				"accessModes": []string{"ReadWriteOnce"},
				"resources": map[string]interface{}{
					"requests": map[string]interface{}{
						"storage": "100Gi",
					},
				},
			},
			Status: map[string]interface{}{
				"phase": "Pending",
			},
			CreatedAt: time.Now(),
			UpdatedAt: time.Now(),
		},
		{
			Type:      "PersistentVolumeClaim",
			Name:      fmt.Sprintf("batch-%s-scripts-pvc", job.JobID),
			Namespace: "batch",
			Spec: map[string]interface{}{
				"accessModes": []string{"ReadWriteOnce"},
				"resources": map[string]interface{}{
					"requests": map[string]interface{}{
						"storage": "10Gi",
					},
				},
			},
			Status: map[string]interface{}{
				"phase": "Pending",
			},
			CreatedAt: time.Now(),
			UpdatedAt: time.Now(),
		},
	}

	return resources, nil
}

// GetResourceTemplates gets resource templates for a batch job
func (h *BatchJobTypeHandler) GetResourceTemplates(job *mysql.Job) ([]*job_manager.ResourceTemplate, error) {
	templates := []*job_manager.ResourceTemplate{
		{
			Type:        "Job",
			Name:        "batch-job-template",
			Namespace:   "batch",
			Description: "Batch processing job template",
			Template: map[string]interface{}{
				"apiVersion": "batch/v1",
				"kind":       "Job",
				"metadata": map[string]interface{}{
					"labels": map[string]interface{}{
						"app":      "batch-processor",
						"job-id":   "{{.JobID}}",
						"job-type": "batch",
					},
				},
				"spec": map[string]interface{}{
					"parallelism": "{{.Parallelism}}",
					"completions": "{{.Parallelism}}",
					"template": map[string]interface{}{
						"spec": map[string]interface{}{
							"restartPolicy": "OnFailure",
							"containers": []map[string]interface{}{
								{
									"name":  "batch-processor",
									"image": "{{.Image}}",
									"command": []string{
										"{{.ScriptPath}}",
									},
									"args": []string{
										"--input", "{{.InputPath}}",
										"--output", "{{.OutputPath}}",
									},
									"resources": map[string]interface{}{
										"requests": map[string]interface{}{
											"cpu":    "{{.CPU}}",
											"memory": "{{.Memory}}",
										},
										"limits": map[string]interface{}{
											"cpu":    "{{.CPULimit}}",
											"memory": "{{.MemoryLimit}}",
										},
									},
								},
							},
						},
					},
				},
			},
			Parameters: h.supportedParameters,
		},
	}

	return templates, nil
}

// StartJob starts a batch job
func (h *BatchJobTypeHandler) StartJob(ctx context.Context, job *mysql.Job) error {
	// Batch-specific startup logic
	// This could include:
	// - Setting up the batch processing environment
	// - Preparing input data
	// - Configuring parallel workers
	// - Setting up monitoring and logging

	return nil
}

// StopJob stops a batch job
func (h *BatchJobTypeHandler) StopJob(ctx context.Context, job *mysql.Job) error {
	// Batch-specific shutdown logic
	// This could include:
	// - Graceful shutdown of workers
	// - Saving intermediate results
	// - Cleanup of temporary files
	// - Finalizing output data

	return nil
}

// GetJobStatus gets the status of a batch job
func (h *BatchJobTypeHandler) GetJobStatus(ctx context.Context, job *mysql.Job) (*mysql.JobStatus, error) {
	// Batch-specific status logic
	// This could include:
	// - Checking job completion status
	// - Getting progress information
	// - Checking resource usage
	// - Monitoring worker status

	status := &mysql.JobStatus{
		JobID:     job.JobID,
		Status:    string(job_manager.JobStateRunning),
		Message:   "Batch job is running",
		CreatedAt: time.Now(),
	}

	return status, nil
}
